/**
 * 上下文菜单
 */
function scContextMenu(opt){
    var com = scCommon.instance();
    var crEle = com.crEle;

    opt = opt ? opt : {};

    var menus = opt.menus;
    var buttons = [];

    var contextmenu = null;
    
    var currentPosition = null;
    var currentElement = null;
    var currentAttributes = null;

    var dialog = new scDialog();
    var ul = null;

    this.createView = function(){
        contextmenu = crEle("div", "sc-context-menu");

        ul = crEle("ul");

        contextmenu.appendChild(ul);

        contextmenu.addEventListener("click", (e)=>{
            let target = null;
            if(e.target.tagName.toLowerCase() == "li"){
                target = e.target
            }else{
                for(let t = e.target.parentNode; t != null; t = t.parentNode){
                    if(t.tagName && t.tagName.toLowerCase() == "li"){
                        target = t;
                        break;
                    }
                }
            }

            if(target){
                hideContextmenu();
                let btn = {...buttons.find(it=>it.node === target)};
                parseAttribute(currentElement, btn);
                triggerListener("click", btn);
            }
        });

        addGlobalListener();

        return contextmenu;
    }

    /**
     * 加载菜单
     * @param {*} ul 
     * @param {*} menus 
     * @param {*}
     */
    var loadMenu = function(ul, menus){
        ul.innerHTML = "";

        let li = null;
        let label = null;
        let menu = null;

        for(var i in menus){
            menu = {...menus[i]};

            buttons.push(menu);

            li = crEle("li");
            ul.appendChild(li);

            let imgContainer = crEle("span");
            imgContainer.classList.add("sc-menu-img");

            li.appendChild(imgContainer);

            if(menu.icon){
                let img = crEle("img");
                img.src = menu.icon;

                imgContainer.appendChild(img);
            }

            label = crEle("span");
            label.classList.add("sc-menu-label");
            label.innerText = menu.label;    

            li.appendChild(label);

            if(menu.shortcutKey || menu.shortcutKeyDisplay){
                let span = crEle("span");
                span.classList.add("sc-menu-short");
                span.innerText = menu.shortcutKey ? menu.shortcutKey : menu.shortcutKeyDisplay;
                li.appendChild(span);
            }

            menu.node = li;

            try{
                if(menu.component && menu.component.name){
                    let exp = "new " + menu.component.name;
    
                    if(menu.component.param){
                        if(typeof(menu.component.param) == "object"){
                            exp += "(" + JSON.stringify(menu.component.param) + ")";
                        }else{
                            exp += "('" + menu.component.param + "')";
                        }
                    }else{
                        exp += "()";
                    }
    
                    menu.component = eval(exp);
                }
            }catch(e){
                console.error("component " + menu.component.name + " is not found");
            }

            if(menu.split){
                li = crEle("li");
                li.classList.add("sc-menu-split");
                ul.appendChild(li);
            }
        }
    }

    /**
     * 显示对话框
     * @param {*} button 
     * @param {*} listener 
     */
    var showDialog = function(button, listener){
        dialog.createView(button, listener);
        dialog.beforeSubmit = function(data){
            return {
                position: currentPosition,
                attributes: data
            }
        }
    }
    
    /**
     * 添加监听器
     */
    var addGlobalListener = function(){
        window.removeEventListener("keydown", windowKeydown);
        window.addEventListener("keydown", windowKeydown);
    }

    /**
     * 键盘事件
     * @param {*} e 
     */
    var windowKeydown = function(e){
        if(!e.ctrlKey && !e.shiftKey && !e.altKey) return;

        var shortKey = "";

        if(e.ctrlKey){
            shortKey += "Ctrl";
        }

        if(e.altKey){
            shortKey += (shortKey ? "+" : "") + "Alt";
        }

        if(e.shiftKey){
            shortKey += (shortKey ? "+" : "") + "Shift"; 
        }

        shortKey += "+" + e.key;

        let btnKey = null;
        let btn = null;

        for(var i in buttons){
            btn = buttons[i];
            if(!btn.shortcutKey) continue;

            btnKey = btn.shortcutKey.toLowerCase();

            if(btnKey.replace(/[\s]/g, "") == shortKey.toLowerCase()){
                triggerListener("click", btn);

                e.stopPropagation();
                e.preventDefault();
                
                break;
            }
        }
    }

    /**
     * 接收通知
     * @param {*} eventType 
     * @param {*} option 
     */
    this.notify = function(eventType, option){
        if(eventType == "mousedown"){
            if(option.nativeEvt.button == 2){

                currentPosition = option.position;
                currentElement = option.belong ? option.belong.element : option.element;
                currentAttributes = option.belong ? option.belong.element.attributes : option.attributes;
                
                filterMenu(currentElement, option.containerType);

                contextmenu.classList.add("active");
                contextmenu.style.left = option.nativeEvt.pageX + "px";
                contextmenu.style.top = option.nativeEvt.pageY + "px";
            }else{
                hideContextmenu();
            }
        }
    }

    /**
     * 过滤菜单
     * @param {*} element 
     * @param {*} containerType
     */
    var filterMenu = function(element, containerType){
        let menuList = [];
        let menu = null;
        let regular = null;

        for(let i = 0; i < menus.length; i++){
            menu = menus[i];
            regular = parseSelector(menu.selector);
            
            if(matchSelector(regular, element, containerType)){
                menuList.push(menu);
            }
        }

        loadMenu(ul, menuList);
    }

    /**
     * 解析选择器
     * @param {*} selector 
     */
    var parseSelector = function(selector){
        var obj = {
            type: null,
            keyVals: {},
            props:[]
        };

        var chars = "[a-z0-9_]+";
        var rule = "^(" + chars + "){0,1}[\s]*(\[[\s]*" + chars + "[\s]*[=]*[\s]*" + chars + "[\s]*\]){0,9}$";
        var regex = new RegExp(rule, "gi");

        var groups = regex.exec(selector);

        for(var i = 1; i < groups.length; i++){
            if(!groups[i]) continue;
            
            if(groups[i].indexOf("=") > -1){
                let arr = groups[i].replace(/[\[\]'']/g, "").split("=");
                obj.keyVals[arr[0]] = arr[1];
            }else if(groups[i].indexOf("[") > -1){
                obj.props.push(groups[i].replace(/[\[\]'']/g, ""));
            }else if(groups[i] != "undefined"){
                obj.type = groups[i].trim();
            }
        };

        return obj;
    }

    /**
     * 元素是否匹配选择器
     * @param {*} regular 
     * @param {*} element 
     * @param {*} containerType
     */
    var matchSelector = function(regular, element, containerType){
        let isMatch = true;

        if(regular.type != null){
            isMatch = (regular.type == element._sType || 
                regular.type == element._pType || regular.type == containerType);
        }
        
        for(let i in regular.props){
            if(element[regular.props[i]] == null){
                isMatch = false;
                break;
            }
        }

        for(let i in regular.keyVals){
            if(element[i] != regular.keyVals[i]){
                isMatch = false;
                break;
            }
        }

        return isMatch;
    }

    /**
     * 隐藏菜单
     */
    var hideContextmenu = function(){
        contextmenu.classList.remove("active");
    }

    /**
     * 监听器
     */
    var listener = {};

    /**
     * 添加监听器
     * @param {*} name 
     * @param {*} callback 
     */
    this.addEventListener = function(name, callback){
        if(!listener[name]){
            listener[name] = [];
        }

        listener[name].push(callback);
    }

    /**
     * 解析属性
     * @param {*} element 
     * @param {*} button 
     */
    var parseAttribute = function(element, button){
        if(!button.routers) return;

        let r = button.routers.find(router=>{
            if(router.type){
                let flg = router.type == element._sType;
    
                if(element.presentType != null){
                    flg = element.presentType == router.presentType;
                }
        
                return flg;
            }
            
            return true;
        });

        let component = eval("new " + r.component.name + "()");

        if(component.setOption){
            component.setOption({
                data: currentAttributes
            });
        }

        if(r.component.method){
            button.component = component[r.component.method](currentAttributes);
        }else{
            button.component = component;
        }
    }

    /**
     * 触发监听
     * @param {*} name 
     * @param {*} button 
     */
    var triggerListener = function(name, button){
        if(!listener[name] || !button) return;
        for(var i in listener[name]){
            if(button.present == "dialog"){
                showDialog(button, listener[name][i]);
            }else{
                listener[name][i](button.command, button.param);
            }
        }
    }

    /**
     * 设置所在布局大小
     * @param {*} lay 
     */
    this.setLayout = function(lay){
        dialog.setLayout(lay);
    }
}